package com.qiudao.commonutil.util;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * Description: Map Util 工具类
 * 依赖 commons-beanutils.commons-beanutils
 *      org.apache.commons.lang3
 * @author: gdc
 * @date: 2019/9/1
 * @version 1.0
 */
public class MapUtil {

    private static final Object[] EMPTY_ARRAY = {};

    /**
     * 将一个bean转换成map
     *
     * @param map
     * @param bean
     * @return
     */
    public static Map populateMap(Map map, Object bean) {
        return populateMap(map, bean, null);
    }

    /**
     * 假设prefix=detail.，bean带有一个属性name，则map中将有一个项： key=detail.name，value为bean的name属性值。
     */
    public static Map populateMap(Map map, Object bean, String prefix) {
        boolean withoutPrefix = StringUtils.isBlank(prefix);
        if (null == bean) {
            return map;
        }
        try {
            Method[] methods = bean.getClass().getMethods();
            for (int i = 0; i < methods.length; i++) {
                String methodName = methods[i].getName();
                Class[] pts = methods[i].getParameterTypes();
                Class rt = methods[i].getReturnType();

                if (methodName.length() > 3 && methodName.startsWith("get") && pts.length == 0 && !Void.class.equals(rt)) {
                    String propName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
                    if ("class".equals(propName)) {
                        continue;
                    }

                    String key = withoutPrefix ? propName : prefix + propName;

                    Object value = methods[i].invoke(bean, EMPTY_ARRAY);
                    if (value != null) {
                        map.put(key, value);
                    }
                }
            }

            return map;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将map转换成bean
     *
     * @param bean
     * @param map
     * @return
     */
    public static Object populateBean(Object bean, Map map) {
        try {
            BeanUtils.populate(bean, map);
            return bean;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 假设prefix=detail.，若map中带有一个key为detail.name， 则bean.setName被调用，参数值为该key对应的value。
     */
    public static Object populateBean(Object bean, Map map, String prefix) {
        boolean withoutPrefix = StringUtils.isBlank(prefix);
        Map m = new HashMap();

        try {
            Method[] methods = bean.getClass().getMethods();
            for (int i = 0; i < methods.length; i++) {
                String methodName = methods[i].getName();

                if (methodName.startsWith("set")) {
                    String propName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
                    String key = withoutPrefix ? propName : prefix + propName;

                    Object value = map.get(key);
                    if (value != null) {
                        Class[] pts = methods[i].getParameterTypes();
                        if (pts.length == 1) {
                            Class cls = pts[0];
                            if (cls.isArray()) {
                                cls = cls.getComponentType();
                            }

                            m.put(propName, value);
                        }
                    }
                }
            }
            BeanUtils.populate(bean, m);
            return bean;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Map<String, Object> generateMap(Map<String, Object> map, String key, Object value) {
        if (map == null) {
            map = new HashMap<String, Object>();
        }
        MapUtils.safeAddToMap(map, key, value);
        return map;
    }

}
